package com.kanche.bigbaby.collection;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import com.kanche.bigbaby.collection.domain.Gallery;
import com.kanche.bigbaby.collection.domain.Photo;
import com.kanche.bigbaby.collection.domain.Vehicle;
import com.kanche.bigbaby.collection.domain.VehicleUploadPhase;
import com.squareup.tape.Task;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

import retrofit.RetrofitError;
import retrofit.client.Response;
import retrofit.mime.TypedFile;


/**
 * Uploads the specified file to imgur.com.
 */
public class VehicleUploadTask implements Task<VehicleUploadTask.Callback> {
    public static final int UPLOAD_AND_DISTRIBUTE_VEHICLE = -1;
    public static final int UPLOAD_AND_SUBSTITUTE_VEHICLE = 1;
    public static final int UPLOAD_ONLY = 0;
    private static final long serialVersionUID = 126142781146165256L;
    private static final String TAG = "Merchant:ImageUploadTask";
    private static final Handler MAIN_THREAD = new Handler(Looper.getMainLooper());
    private final Vehicle vehicle;
    private final long batchId;
    private final Context context;
    private final int action;
    private final ArrayList<CharSequence> shareAccounts;
    private BlockingDeque<Photo> toBeUploadedPhotos = new LinkedBlockingDeque<Photo>();
    private List<Photo> uploadedPhotos = new ArrayList<Photo>();
    private List<Photo> onLinePhotos = new ArrayList<Photo>();
    private int totalPhotos;


    public VehicleUploadTask(Vehicle vehicle, long batchId, Context context, int action) {
        this.batchId = batchId;
        this.vehicle = vehicle;
        this.context = context;
        this.action = action;
        shareAccounts = null;
    }

    public VehicleUploadTask(Vehicle vehicle, long batchId, Context context, int action, ArrayList<CharSequence> ids) {
        this.batchId = batchId;
        this.vehicle = vehicle;
        this.context = context;
        this.action = action;
        shareAccounts = ids;
    }

    public long vehicleRowId() {
        return vehicle.get_id();
    }

    @Override
    public void execute(final Callback callback) {
        startPostVehicle(callback);
    }

    private void startPostVehicle(Callback callback) {
        vehicle.washDataForDearServer();
        if (!vehicle.isIntegral()) {
            return;
        }
        uploadPhotos(callback);
    }

    //Step 1: upload photos
    private void uploadPhotos(final Callback callback) {
        if (vehicle == null) return;
        List<Photo> ps = vehicle.getGallery().getPhotos();

        for (Photo photo : ps) {
//            if (StringUtil.hasText(photo.getUri()) && !StringUtil.isHttpPath(photo.getUri())) {
            if (StringUtils.hasText(photo.getUri())) {
                if (StringUtils.isHttpPath(photo.getUri()))
                    onLinePhotos.add(photo);
                else
                    toBeUploadedPhotos.add(photo);
            }
        }
        totalPhotos = toBeUploadedPhotos.size();

        if (toBeUploadedPhotos.size() == 0) {
//            createVehicle(callback);
            createGallery(callback);
        } else {
            uploadPhoto(toBeUploadedPhotos.peek(), callback);
        }
    }

    private void uploadPhoto(final Photo photo, final Callback callback) {
        MAIN_THREAD.post(new Runnable() {
            @Override
            public void run() {
                callback.onProgress(vehicle, VehicleUploadPhase.UPLOAD_PHOTO
                        .setCurrent(uploadedPhotos.size() + 1)
                        .setTotalPhotos(totalPhotos)
                        , batchId);
            }
        });
        TypedFile file = new TypedFile("image/jpeg", new File(photo.getUri()));
        getBSSService().uploadPhoto(file, "origin", new retrofit.Callback<Map<String, String>>() {
            @Override
            public void success(Map<String, String> map, Response response) {
                final Photo result = new Photo();
                result.setKey(photo.getKey());
                result.setUri(map.get("result"));
                uploadedPhotos.add(result);
                vehicle.getGallery().update(result);
                MAIN_THREAD.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onSuccess(vehicle,
                                VehicleUploadPhase.UPLOAD_PHOTO
                                        .setPhoto(result)
                                        .setTotalPhotos(totalPhotos)
                                        .setCurrent(uploadedPhotos.size()),
                                batchId
                        );
                    }
                });
                toBeUploadedPhotos.remove();
                if (toBeUploadedPhotos.size() != 0) {
                    uploadPhoto(toBeUploadedPhotos.peek(), callback);
                } else {
                    createGallery(callback);
                }
            }

            @Override
            public void failure(final RetrofitError error) {
                final VehicleUploadPhase phase = VehicleUploadPhase.UPLOAD_PHOTO;
                phase.setCurrent(uploadedPhotos.size() + 1);
                phase.setTotalPhotos(totalPhotos);
                MAIN_THREAD.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure(error, vehicle, phase, batchId);
                    }
                });
            }
        });
    }

    private BSSService getBSSService() {
        return BSSService.Creator.create(context);
    }

    //Step 2: create gallery
    private void createGallery(final Callback callback) {
        if (StringUtils.hasText(vehicle.getGalleryId())) {
            createVehicle(callback);
            return;
        }
        MAIN_THREAD.post(new Runnable() {
            @Override
            public void run() {
                callback.onProgress(vehicle, VehicleUploadPhase.CREATE_GALlERY, batchId);
            }
        });
        final Gallery gallery = new Gallery();


        List<Photo> photos = new ArrayList<Photo>();
        photos.addAll(onLinePhotos);
        photos.addAll(uploadedPhotos);
        for (int i = 0; i < photos.size(); i++) {
            photos.get(i).setKey("photo_" + i);
        }

        gallery.setPhotos(photos);
        getBSSService().createGallery(gallery, new retrofit.Callback<Gallery>() {
            @Override
            public void success(Gallery galleryResult, Response response) {
                vehicle.setGalleryId(galleryResult.getId());
                MAIN_THREAD.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onSuccess(vehicle, VehicleUploadPhase.CREATE_GALlERY, batchId);
                    }
                });
                createVehicle(callback);
            }

            @Override
            public void failure(final RetrofitError error) {
                MAIN_THREAD.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure(error, vehicle, VehicleUploadPhase.CREATE_GALlERY, batchId);
                    }
                });
            }
        });
    }


    //Step 3: create vehicle
    private void createVehicle(final Callback callback) {

        MAIN_THREAD.post(new Runnable() {
            @Override
            public void run() {
                callback.onProgress(vehicle, VehicleUploadPhase.UPLOAD_VEHICLE, batchId);
            }
        });
        if (!StringUtils.hasText(vehicle.getGalleryId())) vehicle.setGalleryId(null);

        retrofit.Callback<Vehicle> uploadCallback = new retrofit.Callback<Vehicle>() {
            @Override
            public void success(final Vehicle result, Response response) {
                if (result != null) {
                    vehicle.setId(result.getId());
                }
                MAIN_THREAD.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onSuccess(vehicle, VehicleUploadPhase.UPLOAD_VEHICLE, batchId);
                    }
                });
            }

            @Override
            public void failure(final RetrofitError error) {
                MAIN_THREAD.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure(error, vehicle, VehicleUploadPhase.UPLOAD_VEHICLE, batchId);
                    }
                });
            }
        };
        if (action == UPLOAD_AND_DISTRIBUTE_VEHICLE) {
            Map<String, Object> body = new HashMap<String, Object>();
            body.put("vehicle", vehicle);
            body.put("shareAccountList", shareAccounts);
            getBSSService().uploadAndDistributeVehicle(body, uploadCallback);
        }
        if (action == UPLOAD_AND_SUBSTITUTE_VEHICLE) {
            getBSSService().uploadAndSubstituteVehicle(vehicle, uploadCallback);
        }
        if (action == UPLOAD_ONLY) {
            getBSSService().createVehicle(vehicle, uploadCallback);
        }

    }


    public interface Callback {
        void onSuccess(Vehicle vehicle, VehicleUploadPhase phase, long batchId);

        void onProgress(Vehicle vehicle, VehicleUploadPhase phase, long batchId);

        void onFailure(RetrofitError error, Vehicle vehicle, VehicleUploadPhase phase, long batchId);
    }

}
